//
// Created by cy on 22-5-4.
//

#ifndef CEC_VISION_ARMOR_HPP
#define CEC_VISION_ARMOR_HPP

#include "all.hpp"

class ArmorFinderPrivate;

enum class enuArmorColor {
    COLOR_RED,
    COLOR_BLUE,
    COLOR_NONE
};

enum class enuArmorType {
    TYPE_SMALL,
    TYPE_BIG,
    TYPE_NONE
};

struct sutFindBar {
    enuArmorColor enemyColor;
    int thresh;
    int maxVal;
    cv::Size2i kernel;
    double areaSize;
    double contourSize;
    double ellipseAngleMin;
    double ellipseAngleMax;
};

struct sutDetectArmor {
    double minAngleDiff;
    double maxAngleDiff;
    double minDevAngle;
    double maxDevAngle;
    double minXDiffRatio;
    double maxXDiffRatio;
    double minYDiffRatio;
    double maxYDiffRatio;
    double minLDiffRatio;
    double maxLDiffRatio;
};

struct sutArmorConfigs {

    sutFindBar findBar;
    sutDetectArmor small = {};
    sutDetectArmor big = {};
};

struct sutBarData {
    cv::Point2f center;
    float longLen;
    float angle;
    int ticks;
    enuArmorType type;

    bool operator<(const sutBarData &s) const {
        return center.x < s.center.x;
    }
};

struct sutArmorData {
    cv::Point2f center;
    float width;
    float height;
    std::array<cv::Point2f, 4> corners;
    int ticks;
    enuArmorType type;
};

struct sutFindBarInfo {
    double areaSize;
    int contourSize;
    double angle;
};

struct sutDetectArmorInfo {
    double angleDiff;
    double devAngle;
    double xDiffRatio;
    double yDffRatio;
    double lengthDiffRatio;
};

typedef std::vector<std::tuple<sutBarData, sutBarData>> BarsTupleVector;
typedef std::vector<sutArmorData> ArmorDataVector;
typedef std::vector<sutBarData> BarDataVector;
typedef std::array<cv::Mat, 5> FrameArray;
typedef std::vector<sutFindBarInfo> BarInfoVector;
typedef std::vector<sutDetectArmorInfo> ArmorInfoVector;

class ArmorFinder {

public:
    explicit ArmorFinder(const std::string &configFile, bool debug = false);

    ~ArmorFinder();

    bool update(int times, const cv::Mat &frame, enuArmorColor team = enuArmorColor::COLOR_NONE);

    ArmorDataVector &result();

    FrameArray &debugFramesInfo();

    BarInfoVector &debugBarsInfo();

    ArmorInfoVector &debugSmallArmorsInfo();

    ArmorInfoVector &debugBigArmorsInfo();

    void updateConfigs(const sutArmorConfigs &configs);

    void saveConfigs(const std::string &configFile);

    sutArmorConfigs &getConfigs();

    void openDebug();

    void closeDebug();

    ArmorFinder(const ArmorFinder &) = delete;

    ArmorFinder &operator=(const ArmorFinder &) = delete;

private:
    ArmorFinderPrivate *m_ptr;
};

#endif //CEC_VISION_ARMOR_HPP
